/**
* Created with JetBrains PhpStorm.
* User: skynet
* Date: 10.01.13
* Time: 14:02
* To change this template use File | Settings | File Templates.
*/

describe('utils', function () {
    describe("should sort arrays", function(){
        it('should sort arrays of numbers', function(){
            expect(utils.sort([2, 4, 3, 0])).toEqual([0, 2, 3, 4]);
        });
        it('should sort arrays of numbers with one element', function(){
            expect(utils.sort([2])).toEqual([2]);
        });
        it('should sort array, of the numbers with undefined', function(){
            expect(utils.sort([2,undefined,3,0])).toEqual([0,2,3,undefined]);
        });
        it('should show an error message, one of the number is Null', function(){
            expect(utils.sort([2,null,3,0])).toEqual([null,0,2,3]);
        });
        it('should show an empty array', function(){
            expect(utils.sort([])).toBeTruthy();
        });

        it('should check, call the function once', function(){
            var spy = sinon.spy(utils, "sort");
            utils.sort([]);
            expect(utils.sort).toHaveBeenCalledOnce();
            spy.restore();
        });

        it('should check, call the function twice', function(){
            var spy = sinon.spy(utils, "sort");
            utils.sort([1,2]);
            utils.sort([]);
            expect(utils.sort).toHaveBeenCalledTwice();
            spy.restore();
        });

        it('should call method and return true', function(){
            var spy = sinon.spy(utils, "sort");
            utils.sort([]);
            expect(utils.sort).toHaveBeenCalled();
            spy.restore();
        });
        it('should test for exist underscore method', function(){
            var underscore = _;
            sinon.spy(underscore, "sortBy");
            var handlerSpy = sinon.spy();
            underscore.sortBy([1, 2, 3, 4, 5, 6], handlerSpy);
            expect(handlerSpy).toHaveBeenCalled();
            underscore.sortBy.restore();
        });
        it('Should set time out befor sort data', function(){
            this.clock = sinon.useFakeTimers();
            var stub = sinon.stub();
            setTimeout(stub(1000));

            this.clock.tick(1000);
            expect(stub).toHaveBeenCalled();
            this.clock.restore();
        });
    });

    describe("should camelize ", function (){


        it("should camelize simple strings array", function(){
            expect(utils.camelize(["aaa", "fooo", "bar"])).toEqual("aaaFoooBar");
        });

        it("should camelize simple strings array with one element", function(){
            expect(utils.camelize(["a"])).toEqual("a");
        });
        it("should show a message, that one of the element is null", function(){
            expect(function(){
                (utils.camelize(["aaa", null, "bar"]))}
                ).toThrow("One of the element is null");
        });
        it("should show a message, that one of the element is undefined", function(){
            expect(function(){
                (utils.camelize(["aaa", "fooo", undefined]))}
                ).toThrow('One of the element is undefined');
        });
        it("should show a message, that array is null", function(){
            expect(function(){
                (utils.camelize(null))}
                ).toThrow();
        });
        it("should show a message, that array is undefined", function(){
            expect(function(){
                utils.camelize(undefined)}
                ).toThrow();
        });
        it("should show a message, that an element of array has an integer symbol", function(){
            expect(utils.camelize(["aaa", "fooo", 123])).toEqual("aaaFooo123");
        });
        it("should output empty array", function(){
            expect(utils.camelize([])).toEqual([]);
        });
        it("should camelize simple strings array, one letter with a capital", function(){
            expect(utils.camelize(["aaa", "fooO", "bar"])).toEqual("aaaFoooBar");
        });
        it("should camelize simple strings array, some letters with a capital", function(){
            expect(utils.camelize(["aaa", "FoOo", "bar"])).toEqual("aaaFoooBar");
        });
        it('should review the call by spy', function(){
            var spy = sinon.spy(utils, 'camelize');
            utils.camelize(['foo']);
            expect(utils.camelize).toHaveBeenCalled();
            spy.restore();
        });
    });

    describe('trim function', function(){

        it('Should show an error message, string is Undefined', function(){
            expect(function(){
                utils.trim(undefined)})
                .toThrow();
        });

        it('Should show an error message, string is Null', function(){
            expect(function(){
                utils.trim(null)})
                .toThrow();
        });

        it('Should show an error message, string is empty', function(){
            expect(function(){
                utils.trim()})
                .toThrow();
        });

        it('Should made trim of the string', function(){
            expect(utils.trim(' foo ')).toEqual('foo');
        });

        it('Should made trim of the last position of the string', function(){
            expect(utils.trim('foo ')).toEqual('foo');
        });

        it('Should made trim of first position fo the string', function(){
            expect(utils.trim(' foo')).toEqual('foo');
        });

        it('Should made trim of the string with many words', function(){
            expect(utils.trim(' foo bar ')).toEqual('foo bar');
        });

        it('Should made trim of the first position of multi string', function(){
            expect(utils.trim(' foo bar')).toEqual('foo bar');
        });

        it('Should made trim of the last position of multi string', function(){
            expect(utils.trim('foo, bar ')).toEqual('foo, bar');
        });

    });
    describe('map function', function(){

        beforeEach(function(){
            this.func = function(radius){
                return (Math.PI.toFixed(3)) * (radius * radius);
            };
        });

        it('Should show an error message, arguments is null', function(){
            expect(function(){
                utils.map(this.func, null)})
                .toThrow();
        });

        it('Should show an error message, element(s) of array is undefined', function(){
            expect(function(){
                utils.map(this.func, [2,undefined, 3])})
                .toThrow();
        });

        it('Should show an error message, element(s) of array is null', function(){
            expect(function(){
                utils.map(this.func, [2,null, 3])})
                .toThrow();
        });

        it('Should show an error message, element(s) of array is empty', function(){
            expect(function(){
                utils.map(this.func, [2,, 3])})
                .toThrow();
        });

        it('Should output an array of circles length', function(){
            expect(utils.map(this.func, [2,3,5])).toEqual([12.568,28.278,78.55]);
        });

        it('Should output an array from input object', function(){
            expect(utils.map(this.func,{R1:2, R2:3, R3:5})).toEqual([12.568,28.278,78.55]);
        });
    });
    describe('Group By function', function(){

        beforeEach(function(){

            this.catalog = [
                {
                    name: 'Ivan',
                    age: 21,
                    status: 'freelancer'
                },
                {
                    name: 'Kate',
                    age: 32,
                    status: 'employee'
                },
                {
                    name: 'Ivan',
                    age: 22
                },
                {
                    name: 'Kate',
                    age: 20,
                    status: 'freelancer'
                },
                {
                    name: 'Sergey',
                    status: 'head of the company'
                }
            ];

            this.expectedGrouping = {
                Ivan: [
                    {
                        name: 'Ivan',
                        age: 21,
                        status: 'freelancer'
                    },
                    {
                        name: 'Ivan',
                        age: 22 }
                ],
                Kate: [
                    {
                        name: 'Kate',
                        age: 32,
                        status: 'employee'
                    },
                    {
                        name: 'Kate',
                        age: 20,
                        status: 'freelancer'
                    }
                ],
                Sergey: [
                    {
                        name: 'Sergey',
                        status: 'head of the company'
                    }
                ]
            };


        });

        it('Should output an object with grouped objects by key', function(){
            expect(utils.groupBy(this.catalog, 'name')).toEqual(this.expectedGrouping);
        });

        it('Should output an object', function(){
            expect(utils.groupBy(this.catalog, 'name')).toEqual(jasmine.any(Object));
        });

        it('Should show an error massage, sorts parameter is null', function(){
            expect(function(){
                utils.groupBy(this.catalog, null)})
                .toThrow('Error. Sorts parameter is null');
        });
        it('Should show an error massage, sorts parameter is undefined', function(){
            expect(function(){
                utils.groupBy(this.catalog, undefined)})
                .toThrow('Error. Sorts parameter is undefined');
        });
        it('Should show an error massage, if input data is not an object', function(){
            expect(function(){
                utils.groupBy('string', 'name')})
                .toThrow('Error. Input data is not an object');
        });
        it('Should return an empty object', function(){
            expect(utils.groupBy({}, 'name')).toBeDefined();
        });
    });



});